/*
 * @Author: your name
 * @Date: 2021-05-26 15:42:23
 * @LastEditTime: 2021-05-26 15:44:00
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: /vite-project/src/hooks/core/useContext.ts
 */

/**
 *  1. Vue 提供了一个 InjectionKey 接口，该接口是扩展 Symbol 的泛型类型。它可用于在提供者和消费者之间同步 inject 值的类型
 */
import {
    InjectionKey,
    provide,
    inject,
    reactive,
    readonly as defineReadonly,
    UnwrapRef,
} from 'vue';

type ShallowUnwrap<T> = {
    [P in keyof T]: UnwrapRef<T[P]>;
};

export interface CreateContextOptions {
    readonly?: boolean;
    createProvider?: boolean;
    native?: boolean;
}

export function createContext<T>(
    context: any,
    key: InjectionKey<T> = Symbol(),
    options: CreateContextOptions = {}
) {
    const { readonly = true, createProvider = false, native = false } = options;

    const state = reactive(context);
    const provideData = readonly ? defineReadonly(state) : state;
    !createProvider && provide(key, native ? context : provideData);

    return {
        state,
    };
}

export function useContext<T>(
    key: InjectionKey<T> = Symbol(),
    defaultValue?: any
): ShallowUnwrap<T> {
    return inject(key, defaultValue || {});
}
